﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace matrixdotnet.Common
{
    /// <summary>
    /// The excellent description, stolen at:
    /// http://www-ksl.stanford.edu/knowledge-sharing/ontologies/html/jat-generic/TIME-RANGE.html
    /// 
    /// TimeRange denotes a certain period of time. It consists of a start time, an end time.
    /// A start time must proceed an end time.
    /// </summary>
    public struct TimeRange
    {
        private DateTime startTime;
        private DateTime endTime;

        public DateTime StartTime
        {
            get { return startTime; }
        }

        public DateTime EndTime
        {
            get { return endTime; }
        }

        public TimeRange(DateTime startTime, DateTime endTime)
        {
            if (startTime >= endTime)
                throw new ArgumentOutOfRangeException(
                    "startTime", startTime, "A start time must proceed an end time");

            this.startTime = startTime;
            this.endTime = endTime;
        }

        public bool Intersects(TimeRange other)
        {
            return HaveIntersection(this, other);
        }

        public static bool HaveIntersection(TimeRange p1, TimeRange p2)
        {
            return p1.StartTime >= p2.StartTime && p1.StartTime <= p2.EndTime || p2.StartTime >= p1.StartTime && p2.StartTime <= p1.EndTime;
        }

        public static IComparer<TimeRange> StartTimeComparer
        {
            get
            {
                return new StartTimeComparerImp();
            }
        }

        public static IComparer<TimeRange> EndTimeComparer
        {
            get
            {
                return new EndTimeComparerImp();
            }
        }

        private struct StartTimeComparerImp : IComparer<TimeRange>
        {
            #region IComparer<TimeRange> Members

            public int Compare(TimeRange x, TimeRange y)
            {
                return x.StartTime.CompareTo(y.StartTime); 
            }

            #endregion
        }

        private struct EndTimeComparerImp : IComparer<TimeRange>
        {
            #region IComparer<TimeRange> Members

            public int Compare(TimeRange x, TimeRange y)
            {
                return x.EndTime.CompareTo(y.EndTime);
            }

            #endregion
        }
    }
}
